package cn.kginglam.dynamic_excel.common.utils;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.concurrent.*;

/**
 * @author: Lam
 * @date: 2021-09-09 17:22
 * @description: 线程池工具类
 */
public class ThreadPoolUtils {

    /* CUP 个数 */
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();

    // We want at least 2 threads and at most 4 threads in the core pool,
    // preferring to have 1 less than the CPU count to avoid saturating
    // the CPU with background work
    /* 核心线程数 */
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));

    /* 最大线程数 */
    //private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int MAXIMUM_POOL_SIZE = 1024;

    /* 存活秒数 */
    private static final int KEEP_ALIVE_SECONDS = 30;

    /* 任务队列 */
    private static final BlockingQueue<Runnable> POOL_WORK_QUEUE =
            new LinkedBlockingQueue<>(128);


    private static ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
            .setNameFormat("demo-pool-%d").build();


    /**
     * An {@link Executor} that can be used to execute tasks in parallel.
     * <p>
     * - 核心线程数
     * - 最大线程数
     * - 任务队列       (必须要设置capacity，默认Integer.MAX_VALUE，一旦任务过多会抛出OOM)
     * - 线程工厂
     * - 拒绝策略
     */
    public static final ThreadPoolExecutor THREAD_POOL_EXECUTOR =
            new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE,
                    15L, TimeUnit.SECONDS,
                    new LinkedBlockingQueue<>(1024),
                    namedThreadFactory,
                    new ThreadPoolExecutor.AbortPolicy());


    /**
     * 关闭线程池
     */
    public static void shutDown() {
        THREAD_POOL_EXECUTOR.shutdown();
    }

    public static String getThreadCount() {
        return "activeCount=" + THREAD_POOL_EXECUTOR.getActiveCount() +
                "  completedCount " + THREAD_POOL_EXECUTOR.getCompletedTaskCount() +
                "  largestCount " + THREAD_POOL_EXECUTOR.getLargestPoolSize();
    }
}
